package com.wondertek.service.service.sys.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wondertek.service.dto.sys.req.SysJobAddReq;
import com.wondertek.service.dto.sys.req.SysJobUpdateReq;
import com.wondertek.service.entity.sys.SysJobPo;
import com.wondertek.service.mapper.sys.SysJobMapper;
import com.wondertek.service.quartz.ScheduleUtils;
import com.wondertek.service.service.sys.ISysJobService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author wangyu
 */
@Service
@Slf4j
public class SysJobServiceImpl extends ServiceImpl<SysJobMapper, SysJobPo> implements ISysJobService {

    @Autowired
    private Scheduler scheduler;


    /**
     * 新增任务
     *
     * @param sysJobAddReq
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String add(SysJobAddReq sysJobAddReq) {
        SysJobPo sysJob = new SysJobPo();
        BeanUtil.copyProperties(sysJobAddReq, sysJob);
        if (this.save(sysJob)) {
            ScheduleUtils.createScheduleJob(scheduler, sysJob);
            return sysJob.getId();
        }
        return null;
    }


    /**
     * 更新定时任务
     *
     * @param sysJobUpdateReq
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateSysJob(SysJobUpdateReq sysJobUpdateReq) {
        SysJobPo sysJob = new SysJobPo();
        BeanUtil.copyProperties(sysJobUpdateReq, sysJob);
        if (this.updateById(sysJob)) {
            this.updateSchedulerJob(sysJob);
            return true;
        }
        return false;
    }

    /**
     * 更新任务
     *
     * @param job
     */
    private void updateSchedulerJob(SysJobPo job) {
        String jobId = job.getId();
        // 判断是否存在
        JobKey jobKey = ScheduleUtils.getJobKey(jobId);
        if (ScheduleUtils.checkExists(scheduler, job)) {
            // 防止创建时存在数据问题 先移除，然后在执行创建操作
            ScheduleUtils.deleteScheduleJob(scheduler, jobId);
        }
        ScheduleUtils.createScheduleJob(scheduler, job);
    }

    /**
     * 检查定时任务是否存在
     *
     * @param id
     * @return
     */
    @Override
    public boolean isCheckExistsJob(String id) {
        SysJobPo job = this.getById(id);
        if (!ScheduleUtils.checkExists(scheduler, job)) {
            log.debug("---------- 定时任务不存在:{}", job.getJobName() + "(" + job.getId() + ")");
            return false;
        } else {
            log.debug("---------- 定时任务存在:{}", job.getJobName() + "(" + job.getId() + ")");
            return true;
        }
    }

    /**
     * 强制重建定时任务
     *
     * @param id
     */
    @Override
    public void foredCreation(String id) {
        SysJobPo job = this.getById(id);
        if (ScheduleUtils.checkExists(scheduler, job)) {
            ScheduleUtils.deleteScheduleJob(scheduler, id);
        }
        ScheduleUtils.createScheduleJob(scheduler, job);
    }

    /**
     * 立即运行任务
     *
     * @param jobId
     */
    @Override
    @Transactional
    public void run(String jobId) {
        SysJobPo sysJobPo = this.getById(jobId);
        ScheduleUtils.run(scheduler, sysJobPo);
    }


    /**
     * 删除定时任务
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeJobById(String id) {
        SysJobPo job = this.getById(id);
        if (this.removeById(id)) {
            ScheduleUtils.deleteScheduleJob(scheduler, id);
            return true;
        }
        return false;
    }

    /**
     * 恢复任务
     *
     * @param jobId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resumeJob(String jobId) {
        SysJobPo sysJobPo = this.getById(jobId);
        sysJobPo.setStatus(0);
        if (this.updateById(sysJobPo)) {
            ScheduleUtils.resumeJob(scheduler, jobId);
            return true;
        }
        return false;
    }

    /**
     * 暂停任务
     *
     * @param jobId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean pauseJob(String jobId) {
        SysJobPo sysJobPo = this.getById(jobId);
        sysJobPo.setStatus(1);
        if (this.updateById(sysJobPo)) {
            ScheduleUtils.pauseJob(scheduler, jobId);
            return true;
        }
        return false;
    }

}
